/**
 *
 * @param placeholderItems {Comment[]}
 * @param srcElements {Element[]}
 * @param cleanupCallbacks {((Element)=>void)[]}
 */
function restoreChildren(placeholderItems,
                         srcElements,
                         cleanupCallbacks = []) {
    for (let index = 0; index < srcElements.length; ++index) {
        const srcElement = srcElements[index];
        const placeholderItem = placeholderItems[index];
        // Node 接口的 getRootNode() 方法返回上下文中的根节点，
        // 如果 shadow DOM 可用，则对 shadow DOM 同样适用
        const parentElement = placeholderItem.parentElement ||
            placeholderItem.getRootNode();
        if (cleanupCallbacks[index]) {
            cleanupCallbacks[index](srcElement);
        }
        if (parentElement && parentElement !== placeholderItem) {
            parentElement.replaceChild(srcElement, placeholderItem);
        }
        delete placeholderItem[index];
    }
    return srcElements;
}

/**
 *
 * @param srcElements {Element[]}
 * @param destination {Element}
 * @param position {String: "beforebegin" | "afterbegin" | "beforeend" | "afterend"}
 * @param prepareCallback {function(Element):void | function(Element):void}
 * @returns {function(): Element[]}
 */
function reparentChildren(srcElements,
                          destination,
                          {
                              position,
                              prepareCallback
                          }) {
    let {length} = srcElements;
    if(length === 0) {
        return () => srcElements;
    }
    let step = 1;
    let index = 0;
    if(position === 'afterbegin' || position === 'afterend') {
        step = -1;
        index = length -1;
    }
    /**
     *
     * @type {Comment[]}
     */
    const placeholderItems = new Array(length);

    /**
     *
     * @type {((Element)=>void)[]}
     */
    const cleanupCallbacks = new Array(length);

    /**
     *
     * @type {Comment}
     */
    const placeholderTemplate = document.createComment(
        'placeholder for reparented element'
    );
    do {
        const srcElement = srcElements[index];
        if(prepareCallback) {
            cleanupCallbacks[index] = prepareCallback(srcElement);
        }
        placeholderItems[index] = placeholderTemplate.cloneNode();
        const parentElement = srcElement.parentElement || srcElement.getRootNode();
        if(parentElement && parentElement !== srcElement) {
            parentElement.replaceChild(placeholderItems[index], srcElement);
        }
        // 将一个给定的元素节点插入到相对于被调用的元素的给定的一个位置。
        // https://developer.mozilla.org/zh-CN/docs/Web/API/Element/insertAdjacentElement
        destination.insertAdjacentElement(position, srcElement);
        index += step;
    } while (--length > 0);
    return function() {
        return restoreChildren(
            placeholderItems,
            srcElements,
            cleanupCallbacks,
        )
    }
}

export {reparentChildren};
